<?php

/**
 *
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */

namespace Wxcrypt;
use think\Log;

class XcxPay
{

    const SSLCERT_PATH = ROOT_PATH.'public/uploads/cert/apiclient_cert.pem';//'证书路径';
    const SSLKEY_PATH  = ROOT_PATH.'public/uploads/cert/apiclient_key.pem';//'证书key路径';
    const MCHID        = '1637518902';//'商户号';
    const APPID        = 'wx4bd6b93f69f561d8';//'app_id';
    const KEY          = '63ff85e837ea2836915886ff51sr5h2j';//'key值';

    /**
     * 付款到微信零钱
     * sOpenid：收款方openid
     * nMoney：转账金额
     */
    public function transfer_batches($sOpenid, $nMoney)
    {
        // 付款到零钱方法url
        $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches';

        // 订单号
        $sOrderId = date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
        // 转账备注 （微信用户会收到该备注）
        $tRemark  = "联合众鑫平台提现";
        // 转账金额：微信是分为单位 *100 转换
        $transfer_amount = $nMoney * 100;
        // 转账接收列表设置
        $transfer_detail_list = array(
            [
                'out_detail_no'   => $sOrderId,                  // 明细单号
                'transfer_amount' => intval($transfer_amount),   // 转账总金额
                'transfer_remark' => $tRemark,                   // 单条转账备注
                'openid'          => $sOpenid,                   // 收款方openid
                // 'user_name'       => '张三',
                // 转账金额 >= 2,000元，收款用户姓名必填
            ],
        );
        // 请求参数设置
        $params = [                                                // 请求参数设置
            'appid'                => self::APPID,                 // 文档顶部定义
            'out_batch_no'         => $sOrderId,                   // 商家批次单号
            'batch_name'           => '用户提现',                 // 转账的名称
            'batch_remark'         => '用户提现',                 // 转账的备注
            'total_amount'         => intval($transfer_amount),    // 转账总金额
            'total_num'            => 1,                           // 转账总笔数
            'transfer_detail_list' => $transfer_detail_list,       // 转账接收列表
        ];
        $http_method = 'POST';
        // 获取token
        $token        = $this->getToken($url,$http_method,$params);
        // 发送请求
        $res          = $this->https_request($url, json_encode($params), $token);
        Log::info($res);
        // 反馈数组化
        $resArr       = json_decode($res, true);
        return $resArr;
        // 存储转账成功信息或别的操作


        // 成功实例返回值
//        {
//            "out_batch_no": "plfk2020042013",                        // wx唯一识别号
//          "batch_id": "1030000071100999991182020050700019480001",  // 商家批次单号
//          "create_time": "2015-05-20T13:29:35.120+08:00"           // 创建时间
//        }
    }


    /**
     * 转账明细查询
     * @param string $out_batch_no  商户系统内部的商家批次单号
     * @param string $out_detail_no 账明细单的唯一标识
     * @return array
     */
    public function transferQuery(string $out_batch_no, string $out_detail_no = ''): array
    {
        $api = 'https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/' . $out_batch_no.'/details/out-detail-no/' . $out_detail_no;
        $query = [];
        if ($out_detail_no) {
            $api .= '/details/out-detail-no/' . $out_detail_no;
        } else {
            $query = [
                'query' => [
                    'need_query_detail' => true,
                    'detail_status'     => 'ALL'
                ]
            ];
        }
        // 获取token
        $token        = $this->getToken($query);
        // 发送请求
        $res          = $this->https_request($api, json_encode($query), $token);
        // 反馈数组化
        $resArr       = json_decode($res, true);
        return $resArr;
    }


    /**
     * @notes 商家明细单号查询
     */
    public function detailsQuery($out_batch_no,$out_detail_no)
    {
        //请求URL
        $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/'.$out_batch_no.'/details/out-detail-no/' . $out_detail_no;
        //请求方式
        $http_method = 'GET';
        //请求参数
        $data = [];
        $token  = $this->getToken($url,$http_method,$data);//获取token
        $result = $this->https_request($url,$data,$token);//发送请求
        $result_arr = json_decode($result,true);
        return $result_arr;
    }


    /**
     * 构造请求
     */
    function https_request($url, $data = null, $token)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, (string)$url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

        // 添加请求头
        $headers =     [
            'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $token,
            'Accept: application/json',
            'Content-Type: application/json; charset=utf-8',
            'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
        ];
        if (!empty($headers)) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    /**
     * 获取token
     */
    public function getToken($url,$http_method ,$data)
    {
                                         // 请求方法（GET,POST,PUT）
        $timestamp   = time();                                  // 请求时间戳
        $url_parts   = parse_url($url);                         // 获取请求的绝对URL
        $nonce       = $timestamp . rand('10000', '99999');     // 请求随机串
        $body        = empty($data) ? '' : json_encode((object)$data);              // 请求报文主体
        $stream_opts = [
            "ssl" => [
                "verify_peer"          => false,
                "verify_peer_name"     => false,
            ]
        ];

        // 证书路径信息：文档顶部定义
        $apiclient_cert_path = self::SSLCERT_PATH;
        $apiclient_key_path  = self::SSLKEY_PATH;

        $apiclient_cert_arr = openssl_x509_parse(file_get_contents($apiclient_cert_path, false, stream_context_create($stream_opts)));
        // 证书序列号
        $serial_no          = $apiclient_cert_arr['serialNumberHex'];
        // 密钥
        $mch_private_key    = file_get_contents($apiclient_key_path, false, stream_context_create($stream_opts));
        // 商户id：文档顶部定义
        $merchant_id        = self::MCHID;
        $canonical_url      = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $message            = $http_method . "\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $body . "\n";
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        // 签名
        $sign   = base64_encode($raw_sign);
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token  = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $merchant_id, $nonce, $timestamp, $serial_no, $sign);
        // 微信返回token
        return $token;
    }

}

